package com.lianzai.wxapp.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lianzai.car.dao.CarLogDao;
import com.lianzai.car.domain.CarLogDO;
import com.lianzai.common.annotation.NoLoginAuthRequired;
import com.lianzai.common.config.RedisUtils;
import com.lianzai.common.config.SendMailConfig;
import com.lianzai.common.config.WxConfig;
import com.lianzai.common.constant.Constant;
import com.lianzai.common.executor.LocalSvrSyncExecutor;
import com.lianzai.common.utils.R;
import com.lianzai.common.utils.UUIDUtil;
import com.lianzai.common.utils.WxUtil;
import com.lianzai.mobile.dao.CommunityInfoDao;
import com.lianzai.mobile.domain.CommunityInfoDO;
import com.lianzai.ticket.model.MerchantTicketDO;
import com.lianzai.ticket.model.Ticket;
import com.lianzai.ticket.model.TicketInstance;
import com.lianzai.ticket.service.TicketService;
import com.lianzai.user.domain.UserInfoDO;
import com.lianzai.user.service.UserInfoService;
import com.lianzai.wxapp.consts.WxappConsts;
import com.lianzai.wxapp.domain.MerchantRegisterInfo;
import com.lianzai.wxapp.global.TicketMap;
import com.lianzai.wxapp.service.MerchantService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Controller
public class WxBusinessController {

    @Autowired
    private WxConfig wxConfig;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private TicketService ticketService;

    @Autowired
    private CarLogDao carLogDao;

    @Autowired
    private CommunityInfoDao communityInfoDao;

    @Value("${wx.ticketTokenValidDuration}")
    private long ticketTokenValidDuration;

    /**
     * 注册商户
     *
     * @param
     * @return
     * @throws Exception
     */
    @NoLoginAuthRequired
    @RequestMapping(value = "/wxapp/login", method = RequestMethod.POST)
    @ResponseBody
    public R login(@RequestBody JSONObject json) throws Exception {

        UserInfoDO user = userInfoService.getByWxOpenId(json.getString("openId"));

        R r = new R();
        if (user == null) {
            r.put("code", 1);
            r.put("msg", "用户未注册");
        } else {
            //商户类型，把营业执照照片的保存路径
            if (user.getRole() == 3) {
                String licensePath = merchantService.getLicensePath(user.getId());
                user.setLicensePath(licensePath);
            }

            r.put("msg", "登录成功");
            r.put("userInfo", user);
        }


        return r;
    }


    @NoLoginAuthRequired
    @RequestMapping(value = "/wxapp/getOpenId", method = RequestMethod.POST)
    @ResponseBody
    public R getOpenId(@RequestBody JSONObject json) throws Exception {

        String code = json.getString("code");

        log.info("微信授权 code : {}", code);
        JSONObject wxJson = WxUtil.getOpenIdForApplet(code, wxConfig.getXiangparkAppId(), wxConfig.getXiangparkAppSecret());
        log.info("根据Code获取微信信息 result : {}", wxJson.toString());

        String openId = wxJson.get("openid").toString();

        R r = new R();
        r.put("openId", openId);

        return r;
    }

    @NoLoginAuthRequired
    @RequestMapping(value = "/wxapp/getGrantTicketUrl", method = RequestMethod.POST)
    @ResponseBody
    public R getGrantTicketUrl(@RequestBody JSONObject json, HttpServletRequest request) {

        try {
            //获取参数，暂不检查参数的有效性
            Long userId = json.getLong("userId");
            Long ticketId = json.getLong("ticketId");
            Long communityId = json.getLong("communityId");

            //查询可用停车券数量
            MerchantTicketDO merchantTicketDO = ticketService.getTicketOverview(userId.intValue());
            if (merchantTicketDO == null || merchantTicketDO.getTicketRemainNum() <= 0) {
                return R.error(1, "没有可用的停车券");
            }

            String token;
            token = (String) request.getSession().getAttribute(WxappConsts.SESSION_ATTR_TICKET_TOKEN);
            if (StringUtils.isNotBlank(token)) {
                TicketInstance ticketInstance = TicketMap.getTicket(token);
                if (ticketInstance != null && ticketInstance.getIssueTime() == 0
                        && System.currentTimeMillis() - ticketInstance.getGenerateTime() <= ticketTokenValidDuration) {
                    String url = WxappConsts.GRANTTICKET_URL_HEAD + "?userId=" + userId + "&ticketId=" + ticketId
                            + "&communityId=" + communityId + "&token=" + token;

                    R r = R.ok();
                    r.put("url", url);
                    return r;
                }
            }

            token = UUID.randomUUID().toString().replaceAll("-", "");
            request.getSession().setAttribute(WxappConsts.SESSION_ATTR_TICKET_TOKEN, token);

            TicketInstance ticketInstance = new TicketInstance();
            ticketInstance.setTicketId(ticketId);
            ticketInstance.setMerchantId(userId);
            ticketInstance.setCommunityId(communityId);
            ticketInstance.setTicketToken(token);
            ticketInstance.setGenerateTime(System.currentTimeMillis());

            TicketMap.addTicket(ticketInstance);

            String url = WxappConsts.GRANTTICKET_URL_HEAD + "?userId=" + userId + "&ticketId=" + ticketId
                    + "&communityId=" + communityId + "&token=" + token;

            R r = R.ok();
            r.put("url", url);
            return r;
        } catch (Exception e) {
            log.error("Error happened:", e);
            return R.error(500, "服务器错误");
        }
    }

    @NoLoginAuthRequired
    @RequestMapping(value = "/wxapp/getTicket", method = RequestMethod.POST)
    @ResponseBody
    public R getTicket(@RequestBody JSONObject json, HttpServletRequest request) {

        try {
            //获取参数，暂不检查参数的有效性
            Long userId = json.getLong("userId");
            Long communityId = json.getLong("communityId");
            String token = json.getString("token");

            //检查token有效性
            TicketInstance ticketInstance = TicketMap.getTicket(token);
            if (ticketInstance == null
                    || (ticketInstance.getMerchantId() != null && ticketInstance.getMerchantId() != userId)
                    || (ticketInstance.getCommunityId() != null && ticketInstance.getCommunityId() != communityId)
            )
            {
                return R.error(1, "无效的token");
            }

            if (System.currentTimeMillis() - ticketInstance.getGenerateTime() > ticketTokenValidDuration
                    && ticketTokenValidDuration > 0) {
                TicketMap.removeTicket(token);

                return R.error(1, "无效的token");
            }

            if (ticketInstance.getIssueTime() > 0) {
                return R.error(2, "此停车券已被领取，请刷新商户停车券二维码重新领取");
            }

            //获取停车券信息
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("userId", userId);
            params.put("communityId", communityId);
            Ticket ticket = ticketService.getTicketSpecByUserAndCommunity(params);

            //记录领取时间
            ticketInstance.setIssueTime(System.currentTimeMillis());

            R r = R.ok();
            r.put("ticketId", ticket.getId());
            r.put("ticketDuration", ticket.getMinute() * 60);
            r.put("communityName", ticket.getCommunityName());
            r.put("merchantName", ticket.getMerchantName());

            return r;
        } catch (Exception e) {
            log.error("Error happened:", e);
            return R.error(500, "服务器错误");
        }
    }


    @NoLoginAuthRequired
    @RequestMapping(value = "/wxapp/getCarParkInfo", method = RequestMethod.POST)
    @ResponseBody
    public R getCarParkInfo(@RequestBody JSONObject json) {

        String carNumber = json.getString("carNumber");
        Long communityId = json.getLong("communityId");

        List<CarLogDO> carLogs = carLogDao.getEnterAndLeaveByCarNumberAndCommunity(carNumber, communityId);

        if (carLogs == null || carLogs.size() == 0) {
            return R.error(1, "没有车辆停车信息");
        }

        //最近的停车记录是已付费的, 则没有当前需要处理的停车信息
        CarLogDO carLogDO = carLogs.get(0);
        if (carLogDO.getDirection() == 2 && carLogDO.getIsPayed() == 2) {
            return R.error(1, "没有车辆停车信息");
        }

        if (carLogDO.getChargeType() == 1 || carLogDO.getChargeType() == 2
                || carLogDO.getChargeType() == 3 || carLogDO.getChargeType() == 4) {
            return R.error(2, "当前车辆停车免费，不需要使用停车券");
        }

        int parkDuration;
        long enterTime;

        if (carLogs.size() == 2) {
            CarLogDO enterLog = carLogs.get(1);
            parkDuration = (int) (carLogDO.getLogTime().getTime() - enterLog.getLogTime().getTime())/1000;
            enterTime = enterLog.getLogTime().getTime();
        } else {
            parkDuration = (int) (System.currentTimeMillis() - carLogDO.getLogTime().getTime())/1000;
            enterTime = carLogDO.getLogTime().getTime();
        }

        R r = R.ok();
        r.put("carParkDuration", parkDuration);
        r.put("carEnterTime", enterTime);
        r.put("carNumber", carNumber);
        r.put("communityId", communityId);

        return r;
    }


    @NoLoginAuthRequired
    @RequestMapping(value = "/wxapp/useTicket", method = RequestMethod.POST)
    @ResponseBody
    public R useTicket(@RequestBody JSONObject json, HttpServletRequest request) {

        try {
            long ticketId = json.getLong("ticketId");
            int ticketDuration = json.getInteger("ticketDuration");
            long userId = json.getLong("userId");
            long communityId = json.getLong("communityId");
            String carNumber = json.getString("carNumber");
            String token = json.getString("token");

            //检查token有效性
            TicketInstance ticketInstance = TicketMap.getTicket(token);
            if (ticketInstance == null
                    || (ticketInstance.getMerchantId() != null && ticketInstance.getMerchantId() != userId)
                    || (ticketInstance.getCommunityId() != null && ticketInstance.getCommunityId() != communityId)
            ) {
                return R.error(1, "无效的token");
            }

            if (System.currentTimeMillis() - ticketInstance.getIssueTime() > ticketTokenValidDuration
                    && ticketTokenValidDuration > 0) {
                TicketMap.removeTicket(token);

                return R.error(1, "无效的token");
            }

            if (ticketInstance.getBindCarTime() > 0) {
                TicketMap.removeTicket(token);
                return R.error(4, "此停车券已被使用，请刷新商户停车券二维码重新领取");
            }

            //TODO 同一车牌只能使用一张停车券
            List<CarLogDO> carLogs = carLogDao.getEnterAndLeaveByCarNumberAndCommunity(carNumber, communityId);

            if (carLogs == null || carLogs.size() == 0) {
                return R.error(3, "没有车辆停车信息");
            }

            CarLogDO carLogDO;
            if (carLogs.size() == 1) {
                carLogDO = carLogs.get(0);
            } else {
                carLogDO = carLogs.get(1);
            }

            if (carLogDO.getTicketId() != null) {
                return R.error(2, "该车辆已经使用了一张停车券，停车券不能叠加使用");
            }


            carLogDO.setTicketId(ticketId);
            int ticketMinute = ticketDuration / 60;
            carLogDO.setTicketMinute(ticketMinute);
            carLogDO.setTicketUserid(userId);
            carLogDO.setTicketUseStatus(0);
            carLogDO.setTicketBindTime(new Date());

            
            //TODO 同步到本地系统
            CommunityInfoDO communityInfoDO = communityInfoDao.get(Integer.parseInt(communityId+""));
            boolean localSyncRet = LocalSvrSyncExecutor.addTicket(ticketDuration, carNumber, communityInfoDO);
            if (!localSyncRet) {
                return R.error(5, "停车券绑定失败");
            }


            //记录到数据库
            int ret = carLogDao.bindTicket(carLogDO);
            if (ret == 0) {
                return R.error(5, "停车券绑定失败");
            }

            R r = R.ok();
            r.put("ticketUseTime", System.currentTimeMillis());
            r.put("freeParkEndTime", System.currentTimeMillis() + 1800 * 1000);

            //停车券已经被使用，从map中删除
            TicketMap.removeTicket(token);

            return r;
        } catch (Exception e)
        {
            log.error("Error happened:", e);
            return R.error(500, "服务器错误");
        }
    }


}